{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 面向对象\n",
    "* Python从设计之初就已经是一门面向对象的语言，正因为如此，在Python中创建一个类和对象是很容易的。\n",
    "* 如果你以前没有接触过面向对象的编程语言，那你可能需要先了解一些面向对象语言的一些基本特征，在头脑里头形成一个基本的面向对象的概念，这样有助于你更容易的学习Python的面向对象编程。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 面向对象简介\n",
    "* 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。\n",
    "* 方法：类中定义的函数。\n",
    "* 类变量：类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。\n",
    "* 数据成员：类变量或者实例变量用于处理类及其实例对象的相关的数据。\n",
    "* 方法重写：如果从父类继承的方法不能满足子类的需求，可以对其进行改写，这个过程叫方法的覆盖（override），也称为方法的重写。\n",
    "* 实例变量：定义在方法中的变量，只作用于当前实例的类。\n",
    "* 继承：即一个派生类（derived class）继承基类（base class）的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如，有这样一个设计：一个Dog类型的对象派生自Animal类，这是模拟\"是一个（is-a）\"关系（例图，Dog是一个Animal）。\n",
    "* 实例化：创建一个类的实例，类的具体对象。\n",
    "* 对象：通过类定义的数据结构实例。对象包括两个数据成员（类变量和实例变量）和方法。\n",
    "\n",
    "和其它编程语言相比，Python 在尽可能不增加新的语法和语义的情况下加入了类机制。<br>\n",
    "Python中的类提供了面向对象编程的所有基本功能：类的继承机制允许多个基类，派生类可以覆盖基类中的任何方法，方法中可以调用基类中的同名方法。\n",
    "对象可以包含任意数量和类型的数据。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 类定义\n",
    "语法格式如下：\n",
    "```python\n",
    "class ClassName:\n",
    "    <statement-1>\n",
    "    .\n",
    "    <statement-N>\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 类对象\n",
    "* 类对象支持两种操作：属性引用和实例化。\n",
    "* 属性引用使用和 Python 中所有的属性引用一样的标准语法：obj.name。\n",
    "* 类对象创建后，类命名空间中所有的命名都是有效属性名。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "class FirstClass():\n",
    "    name = 'first class'\n",
    "    def show(self):\n",
    "        return 'quant trade'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "fc=FirstClass()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "__main__.FirstClass"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(fc)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "first class quant trade\n"
     ]
    }
   ],
   "source": [
    "print(fc.name,fc.show())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "很多类都倾向于将对象创建为有初始状态的。因此类可能会定义一个名为 \\__init\\__() 的特殊方法（构造方法）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "12.34\n",
      "<class '__main__.KLine'>\n",
      "<class '__main__.KLine'>\n"
     ]
    }
   ],
   "source": [
    "class KLine():\n",
    "    def __init__(quant,close):\n",
    "        quant.close=close\n",
    "        print(quant.close)\n",
    "        print(type(quant))\n",
    "    name = 'k line'\n",
    "    def show(quant):\n",
    "        return 'quant trade'\n",
    "fc = KLine(12.34)\n",
    "print(type(fc))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# self代表类的实例，而非类\n",
    "类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 类的方法\n",
    "在类地内部，使用 def 关键字来定义一个方法，与一般函数定义不同，类方法必须包含参数 self, 且为第一个参数，self 代表的是类的实例。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 继承\n",
    "Python 同样支持类的继承，如果一种语言不支持继承，类就没有什么意义。<br>\n",
    ">```python\n",
    "class DerivedClassName(BaseClassName1,BaseClassName2):\n",
    "    <statement-1>\n",
    "    .\n",
    "    .\n",
    "    .\n",
    "    <statement-N>\n",
    "```\n",
    "\n",
    "<br>\n",
    "需要注意圆括号中基类的顺序，若是基类中有相同的方法名，而在子类使用时未指定，python从左至右搜索 即方法在子类中未找到时，从左到右查找基类中是否包含方法。<br>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "quant 说: 我 18 岁了，我在读 3 年级\n"
     ]
    }
   ],
   "source": [
    "class People():\n",
    "    def __init__(self,n,a,w):\n",
    "        self.name=n\n",
    "        self.age=a\n",
    "        self.__weight=w\n",
    "    def speak(self):\n",
    "        print(\"%s 说: 我 %d 岁。\" %(self.name,self.age))\n",
    "class Student(People):\n",
    "    def __init__(self,n,a,w,g):\n",
    "        People.__init__(self,n,a,w)\n",
    "        self.grade=g\n",
    "#     覆写基类的方法\n",
    "    def speak(self):\n",
    "        print(\"%s 说: 我 %d 岁了，我在读 %d 年级\"%(self.name,self.age,self.grade))\n",
    "s=Student('quant',18,100,3)\n",
    "s.speak()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "我叫 quant，我是一个演说家，我演讲的主题是 learn pyton,make quant trade!\n"
     ]
    }
   ],
   "source": [
    "class Speaker():\n",
    "    def __init__(self,n,t):\n",
    "        self.name=n\n",
    "        self.topic=t\n",
    "    def speak(self):\n",
    "        print(\"我叫 %s，我是一个演说家，我演讲的主题是 %s\"%(self.name,self.topic))\n",
    "class Peopler(Speaker,Student):\n",
    "    def __init__(self,n,a,w,g,t):\n",
    "        Student.__init__(self,n,a,w,g)\n",
    "        Speaker.__init__(self,n,t)\n",
    "peopler=Peopler(n='quant',a=18,w=100,g=3,t='learn pyton,make quant trade!')\n",
    "peopler.speak()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 方法重写\n",
    "如果你的父类方法的功能不能满足你的需求，你可以在子类重写你父类的方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "调用继承类的方法\n"
     ]
    }
   ],
   "source": [
    "class BaseClass():\n",
    "    def show(self):\n",
    "        print('调用基类的方法')\n",
    "class DerivedClass(BaseClass):\n",
    "    def show(self):\n",
    "        print(\"调用继承类的方法\")\n",
    "dc=DerivedClass()\n",
    "dc.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# super() 函数\n",
    "super() 函数是用于调用父类(超类)的一个方法。<br>\n",
    "super 是用来解决多重继承问题的，直接用类名调用父类方法在使用单继承的时候没问题，但是如果使用多继承，会涉及到查找顺序（MRO）、重复调用（钻石继承）等种种问题。<br>\n",
    "MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。<br>\n",
    "# 语法\n",
    "> ```python\n",
    "super(type[, object-or-type])```\n",
    "# 参数\n",
    "* type -- 类。\n",
    "* object-or-type -- 类，一般是 self"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "调用基类的方法\n"
     ]
    }
   ],
   "source": [
    "super(DerivedClass,dc).show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 类属性与方法\n",
    "## 类的私有属性\n",
    "\\__private_attrs：两个下划线开头，声明该属性为私有，不能在类地外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs。\n",
    "## 类的方法\n",
    "在类地内部，使用 def 关键字来定义一个方法，与一般函数定义不同，类方法必须包含参数 self，且为第一个参数，self 代表的是类的实例。<br>\n",
    "self 的名字并不是规定死的，也可以使用 this，但是最好还是按照约定是用 self。\n",
    "## 类的私有方法\n",
    "\\__private_method：两个下划线开头，声明该方法为私有方法，只能在类的内部调用 ，不能在类地外部调用。self.__private_methods。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Order():\n",
    "    def __init__(self,price,vol):\n",
    "        self.price=price\n",
    "        self.vol=vol\n",
    "        self.__id=self.__getid()\n",
    "    def __getid(self):\n",
    "        return 0\n",
    "    def id(self):\n",
    "        return self.__id\n",
    "order=Order(12,100)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "order.id()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 类的专有方法：\n",
    "* \\__init__ : 构造函数，在生成对象时调用\n",
    "* \\__del__ : 析构函数，释放对象时使用\n",
    "* \\__repr__ : 打印，转换\n",
    "* \\__setitem__ : 按照索引赋值\n",
    "* \\__getitem__: 按照索引获取值\n",
    "* \\__len__: 获得长度\n",
    "* \\__cmp__: 比较运算\n",
    "* \\__call__: 函数调用\n",
    "* \\__add__: 加运算\n",
    "* \\__sub__: 减运算\n",
    "* \\__mul__: 乘运算\n",
    "* \\__div__: 除运算\n",
    "* \\__mod__: 求余运算\n",
    "* \\__pow__: 乘方"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 运算符重载\n",
    "Python同样支持运算符重载，我们可以对类的专有方法进行重载"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Vector():\n",
    "    def __init__(self,a,b):\n",
    "        self.a=a\n",
    "        self.b=b\n",
    "    def __str__(self):\n",
    "        return 'Vector (%d, %d)' % (self.a, self.b)\n",
    "    def __add__(self,other):\n",
    "        return Vector(self.a+other.a,self.b+other.b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Vector (10, 10) Vector (20, 30)\n"
     ]
    }
   ],
   "source": [
    "v1=Vector(10,10)\n",
    "v2=Vector(20,30)\n",
    "print(v1,v2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Vector (30, 40)\n"
     ]
    }
   ],
   "source": [
    "print(v1+v2)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
